package com.z.redis;

import com.z.redis.aof.Aof;
import com.z.redis.command.Command;
import com.z.redis.command.CommandFactory;
import com.z.redis.command.WriteCommand;
import com.z.redis.resp.*;
import com.z.redis.util.TRACEID;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import org.apache.log4j.Logger;


/**
 * 解析字节流
 */
public class CommandDecoder extends LengthFieldBasedFrameDecoder {
    private static final Logger LOGGER = Logger.getLogger(CommandDecoder.class);
    private static final int MAX_FRAME_LENGTH = Integer.MAX_VALUE; // 最大帧长度
    private Aof aof = null; // AOF持久化组件

    public CommandDecoder(Aof aof){
        this(); // 无参构造
        this.aof = aof;
    }
    public CommandDecoder(){
        super(MAX_FRAME_LENGTH,0,4); // 最大帧长度 长度字段偏移量 长度字段大小（4字节）
    }

    @Override
    public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception{
        TRACEID.newTraceid(); // 生成请求跟踪ID 用于日志追踪
        while(in.readableBytes()!=0){
            int mark = in.readerIndex(); // 记录当前指针位置 用于异常回滚
            try {
                // 解析Redis协议数据
                Resp resp = Resp.decode(in); // 解析字节流为Redis命令对象
                if(!(resp instanceof RespArray || resp instanceof SimpleString)) {
                    throw new IllegalStateException("客户端命令应为RespArray或SimpleString类型");
                }

                // 转化成Command命令
                Command command = null;
                if(resp instanceof RespArray){
                    command = CommandFactory.from((RespArray) resp);
                }else if(resp instanceof SimpleString){
                    command = CommandFactory.from((SimpleString) resp);
                }

                // 处理无效命令
                if(command == null){
                    // 返回错误响应
                    String errorMsg = "unsupport command:" + ((BulkString) ((RespArray) resp).getArray()[0]).getContent().toUTF8String();
                    ctx.writeAndFlush(new Errors(errorMsg));
                } else {
                    // AOF持久化 (仅写命令)
                    if (aof != null && command instanceof WriteCommand) {
                        aof.put(resp);
                    }
                    return command;
                }
            } catch (Exception e) {
                in.readerIndex(mark);
                LOGGER.error("解码命令失败", e);
                break;
            }
        }
        return null;
    }
}
